Creating registries and devices
This page explains how to create, edit, and delete device registries and devices within them.
A device is a "Thing" in "Internet of Things": a processing unit that is capable of connecting to the internet (directly or indirectly) and exchanging data with the cloud. A device registry is a container of devices with shared properties.
If you haven't already, complete the Getting Started steps before proceeding.
Device Registry
Creating a device registry
To use OmniCore, you must create at least one device registry. You can create a registry using console or using the OmniCore API. Create New Registry
- Console
- go
Go to the Registries page in console.
At the top of the page, click Create a registry.
Enter a Registry ID. For information on registry naming and size requirements, see Permitted characters and size requirements.
Select a telemetry topic from the drop down. (These are topics configured in the sink section.)
(Optional) If you want to publish separate streams of data from a device, add more telemetry topics.
Each topic maps to a subfolder specified in either the MQTT topic path or the HTTP request when the data is published. To create additional telemetry topics:
Click Add more telemetry topics, then click Add topic and subfolder.
Select a Pub/Sub topic.
Enter a descriptive subfolder name.
For information on subfolder naming and size requirements, see Permitted characters and size requirements.
(Optional) Select a Device state topic. This topic can be the same as a telemetry topic, or can be used only for state data.
All State data is published to the above configured Cloud Pub/Sub. OmniCore also persists the last 10 state data but a 1 message per second Rate limiting is applied to the second part.
Select the Protocols that devices in this registry will use to connect to OmniCore: MQTT, HTTP, or both.
Select the Log Level.
(Optional) Enter or Upload a CA Certificate. A CA certificate at registry level adds more security but this is optional. (For Zero Touch Provisioning to work there should be at least 1 CA certiifcate in the registry.). To know more how it works check the Verifying Credentials section.
Click Create to continue.
// createRegistry creates a OmniCore device registry associated with a PubSub topic
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os"
)
var BASEURL = "<BaseUrl>"
var subscription = "<subscriptionId>"
var token = "Bearer <token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries", BASEURL, subscription)
func main() {
var jsonData = []byte(`{"id": "<id>","eventNotificationConfigs": [{"pubsubTopicName": "<topicName>"}]}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header = http.Header{
"Content-Type": {"application/json"},
"Authorization": {token},
}
client := &http.Client{}
res, e := client.Do(req)
if e != nil {
log.Fatal(e)
}
defer res.Body.Close()
fmt.Println("response Status:", res.Status)
fmt.Println("Created registry")
// Print the body to the stdout
io.Copy(os.Stdout, res.Body)
}
Creating a device registry with multiple Pub/Sub topics
As noted in creating a device registry, you must create at least one device registry to use OmniCore. A registry can have one or more Pub/Sub topics to which devices in the registry can publish data.
You can combine Pub/Sub topics with MQTT/HTTP subfolders to publish telemetry events to separate topics. Each topic maps to a subfolder, so when you publish data to the subfolder, it gets forwarded to the topic. For example, you might have a device that publishes multiple types of data, such as temperature, humidity, and logging data. By directing these data streams to their own individual topics, you can eliminate the need to separate the data into different categories after publishing.
You can map a single Pub/Sub topic to multiple subfolders, but the reverse is not true; each subfolder must be unique and a single subfolder cannot be mapped to different topics.
For detailed information on publishing to separate Pub/Sub topics, see the sections on using the MQTT bridge and using the HTTP bridge.
Creating Device
Creating device key pairs
Before creating a device, first create a public/private key pair for it. When connecting to OmniCore, each device creates a JSON Web Token (JWT) signed with its private key, which OmniCore authenticates using the device's public key.
Creating or editing a device
You can create a device or edit an existing one using console, the API. Make sure you've created a registry and a key pair before completing the steps in this section.
Using Console
- Console
- Go to the Registries page in console.
- Click the ID of the registry for the device.
- In the registry menu on the left, click Devices.
- Click Create a device. To edit an existing device, click its ID on the Devices page, and then click Edit device at the top of the page.
- Enter a Device ID that briefly describes the device or otherwise helps you identify it. (This field can't be edited later.) For information on device naming and size requirements, see Permitted characters and size requirements.
- For Device communication, select Allow or Block. This option allows you to block communication when needed, such as when a device is not functioning properly. In most cases, you'll want to allow communication when first creating the device.
- If you're creating a new device, select the Input method you want to use to enter the public key:
- Manual: Copy and paste the public key into the Public key value field.
- Upload: In the Public key value field, click Browse to select a file on your computer.
- Select the Public key format that matches the key pair for this device. Paste the certificate or key in the Public key value field. You can also set an expiration date for the key. To add a key to an existing device, click Add public key on the Device details page.
- Use the Key and Value fields to add optional device metadata, such as a serial number. For information on metadata key-value naming and size requirements, see Permitted characters and size requirements.
- Select a Cloud Logging level to determine which device events are sent to Cloud Logging.
- Click Create to create the device or Update to save changes to an existing device.
Using APIs
Use the following methods to create or edit devices:
Device create method to add devices to registries
Device patch method to edit existing devices
When creating a device, public keys are specified in the credentials field of the Device resource in the OmniCore API. You can also add or modify this field when you update the device resource. If one or more registry-level certificates are present when adding a new device credential (either via device creation or via modifications), the public key credential must be signed by one of the registry-level certificates. See DeviceCredential in the Device resource for more information.
For RSA, theDevice.credentials[i].public_key.key field must be set to the contents of rsa_cert.pem (including the header and the footer). The Device.credentials[i].public_key.format field must be set to RSA_PEM or RSA_X509_PEM.
For ES256, the Device.credentials[i].public_key.key field must be set to the contents of ec_public.pem (including the header and the footer). The Device.credentials[i].public_key.format field must be set to ES256_PEM or ES256_X509_PEM.
The following sample shows how to create a device with RSA credentials: Create New Device
- go
// Creates a device in a registry given RSA X.509 credentials.
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os"
)
var BASEURL = "<BaseUrl>"
var subscription = "<subscriptionId>"
var registryId = "<registryId>"
var token = "Bearer <token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices", BASEURL, subscription, registryId)
func main() {
var jsonData = []byte(` {"id": "deviceId","credentials": [{"publicKey": {"format": "RSA_X509_PEM", "key": "<PublicKeyBytes>"}}]}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header = http.Header{
"Content-Type": {"application/json"},
"Authorization": {token},
}
client := &http.Client{}
res, e := client.Do(req)
if e != nil {
log.Fatal(e)
}
defer res.Body.Close()
fmt.Println("response Status:", res.Status)
fmt.Println("Created Device")
// Print the body to the stdout
io.Copy(os.Stdout, res.Body)
}
The following sample shows how to create a device with Elliptic Curve (EC) credentials:
- go
// Creates a device in a registry given RSA X.509 credentials.
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os"
)
var BASEURL = "<BaseUrl>"
var subscription = "<subscriptionId>"
var registryId = "<registryId>"
var token = "Bearer <token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices", BASEURL, subscription, registryId)
func main() {
var jsonData = []byte(` {"id": "deviceId","credentials": [{"publicKey": {"format": "ES256_PEM", "key": "<PublicKeyBytes>"}}]}`)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header = http.Header{
"Content-Type": {"application/json"},
"Authorization": {token},
}
client := &http.Client{}
res, e := client.Do(req)
if e != nil {
log.Fatal(e)
}
defer res.Body.Close()
fmt.Println("response Status:", res.Status)
fmt.Println("Created Device")
// Print the body to the stdout
io.Copy(os.Stdout, res.Body)
}
The following sample shows how to patch a device with RSA credentials: Modify A Device
- go
// patchDeviceRSA patches a device to use RSA256 X.509 credentials.
package main
import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"os"
)
var BASEURL = "<BaseUrl>"
var subscription = "<subscriptionId>"
var registryId="<registryId>"
var deviceId="<deviceId>"
var token = "Bearer <token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices/%s?updateMask=mqtt_config", BASEURL, subscription,registryId,deviceId)
func main() {
var jsonData = []byte(`{"mqttConfig":{"mqttEnabledState": "MQTT_ENABLED"}}`)
req, _ := http.NewRequest("PATCH", url, bytes.NewBuffer(jsonData))
req.Header = http.Header{
"Content-Type": {"application/json"},
"Authorization": {token},
}
client := &http.Client{}
res, e := client.Do(req)
if e != nil {
log.Fatal(e)
}
defer res.Body.Close()
fmt.Println("response Status:", res.Status)
fmt.Println("Modified device")
// Print the body to the stdout
io.Copy(os.Stdout, res.Body)
}
Credential and certificate expiration dates
When you create a device and add a public key, you can set an expiration date for the key. If the key was generated with a self-signed X.509 certificate, then the certificate itself also has an expiration date. However, these two expiration dates are separate.
If either the key expires or the self-signed X.509 certificate on the key expires, the device will not be able to connect to OmniCore. Additionally, if you try to create or update a device with an expired X.509 certificate, OmniCore returns an error.
Getting device details
You can get details about one or more devices using console, the API.
Using Console
- Console
Go to the Registries page in console.
Click the ID of the registry for the device.
In the menu on the left, click Devices.
Click the ID of the device to go to the Device details page. This page summarizes recent device activity, including the last time a message was published and the time of the most recent error. This page also shows the device numeric ID.
Click the Configuration & state history tab to see recent configuration versions and update times for the device.
The fields for the last heartbeat time and the last time a configuration was ACKed are for the MQTT bridge only. The HTTP bridge does not support heartbeat or explicit ACKs.
Using APIs
Use the following methods to get details about devices:
Device list method to list the devices in a registry
Device get method to get details about a device
Device states list method to list the last few versions of the device state in descending order
The following sample shows how to list the devices in a registry: List All Devices
- go
// listDevices gets the identifiers of devices for a specific registry.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
var BASEURL = "<BASEURL>"
var subscription = "<subscriptionId>"
var registryId = "registryId"
var token = "Bearer <Token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices", BASEURL, subscription, registryId)
func main() {
client := http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
//Handle Error
}
req.Header = http.Header{
"Authorization": {token},
}
res, err := client.Do(req)
//We Read the response body on the line below.
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatalln(err)
}
//Convert the body to type string
sb := string(body)
log.Printf(sb)
}
The following sample shows how to retrieve a device and its metadata from a device registry: Get a Device
- go
// getDevice retrieves a specific device and prints its details.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
var BASEURL = "<BASEURL>"
var subscription = "<subscriptionId>"
var registryId = "registryId"
var deviceId = "<deviceId>"
var token = "Bearer <Token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices/%s", BASEURL, subscription, registryId,deviceId)
func main() {
client := http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
//Handle Error
}
req.Header = http.Header{
"Authorization": {token},
}
res, err := client.Do(req)
//We Read the response body on the line below.
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatalln(err)
}
//Convert the body to type string
sb := string(body)
log.Printf(sb)
}
The following sample shows how to retrieve device state from a device registry: Get Device State
- go
// getDeviceStates retrieves and lists device states.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
var BASEURL = "<BASEURL>"
var subscription = "<subscriptionId>"
var registryId = "<registryId>"
var deviceId = "<deviceId>"
var token = "Bearer <Token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices/%s/states", BASEURL, subscription, registryId,deviceId)
func main() {
client := http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
//Handle Error
}
req.Header = http.Header{
"Authorization": {token},
}
res, err := client.Do(req)
//We Read the response body on the line below.
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatalln(err)
}
//Convert the body to type string
sb := string(body)
log.Printf(sb)
}
See the Device Management Samples for more code samples.
Deleting devices and registries
- Console
You can delete devices and registries using console, the API. To delete a registry, first delete all the devices within it.
You can delete one or more devices from the registry's list of devices.
To delete devices:
1. Go to the Registries page in console.
2. Click the ID of the registry for the device.
3. In the menu on the left, click Devices.
4. Select each device you want to delete, then click Delete.
5. Confirm you want to delete the selected devices, then click Delete.
Using APIs
Use the following methods to delete devices and registries:
- Device delete method to delete a device.
- Registries delete method to delete a registry
The following sample shows how to delete a device from a registry: Delete a Device
- go
// deleteDevice deletes a device from a registry.
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
var BASEURL = "<BASEURL>"
var subscription = "<subscriptionId>"
var registryId = "registryId"
var deviceId = "deviceId"
var token = "<Bearer Token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s/devices/%s", BASEURL, subscription, registryId, deviceId)
func main() {
client := http.Client{}
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
//Handle Error
}
req.Header = http.Header{
"Authorization": {"Bearer Token"},
}
res, err := client.Do(req)
//We Read the response body on the line below.
respBody, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
// Display Results
fmt.Println("response Status : ", res.Status)
fmt.Println("response Headers : ", res.Header)
fmt.Println("response Body : ", string(respBody))
}
The following sample shows how to delete a registry: Delete a Registry
- go
// deleteRegistry deletes a device registry if it is empty.
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
var BASEURL = "<BASEURL>"
var subscription = "<subscriptionId>"
var registryId = "registryId"
var token = "<Bearer Token>"
var url = fmt.Sprintf("%s/subscriptions/%s/registries/%s", BASEURL, subscription, registryId)
func main() {
client := http.Client{}
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
//Handle Error
}
req.Header = http.Header{
"Authorization": {"Bearer Token"},
}
res, err := client.Do(req)
//We Read the response body on the line below.
respBody, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
// Display Results
fmt.Println("response Status : ", res.Status)
fmt.Println("response Headers : ", res.Header)
fmt.Println("response Body : ", string(respBody))
}